/***************************************************************************
 *   oboe.resources.Files						  *
 *   Copyright (C) 2011 by Felipe Manga					*
 *   lufeboma@gmail.com							*
 *									 *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the	   *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to	*
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:						 *
 *									 *
 *   The above copyright notice and this permission notice shall be	*
 *   included in all copies or substantial portions of the Software.	   *
 *									 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,	   *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF	*
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR	 *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.					   *
 ***************************************************************************/

// In case of the following error, use this link.
// Error #2044: SecurityErrorEvent: não manipulado. text=Error #2140: Violação da área de segurança: [...]
// http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html

package oboe.resources;

import flash.system.ApplicationDomain;
import flash.utils.Dictionary;
import flash.utils.setTimeout;

import oboe.core.Oboe;
import oboe.core.SigSlot;

class Files{

private static var _instance : Files;

// stores all the files indexed by their handles
private static var _fileIndex : Dictionary = new Dictionary();

public function new() {
	FileRef.onLoadCallback = onLoad;
}

private static var instance(getInstance, null):Files;
 	private function getInstance() : Files {
	if( !_instance ) _instance = new Files();
	return _instance;
} 

public static function registerResource( path : String, obj : Object, appDomain:ApplicationDomain ) : Void {
	var ref : FileRef = new FileRef(path, "");
	_fileIndex[ ref.handle ] = ref;
	ref.appDomain = appDomain;
	ref.object = obj;
}

public static function getFile( handle : String ) : Object {
	if( handle == null ) return null;
	return _fileIndex[handle].object; 
}

public static function getClass( handle : String, className : String ) : Class {
	return (_fileIndex[handle] as FileRef).appDomain.getDefinition(className) as Class;
}

public static function getInstance( handle : String, className : String ) : Object {
	var C : Class = getClass(handle, className );
	return new C();
}

public static function getStaticInstance( handle : String, className : String ) : Object {
	var ref : FileRef = _fileIndex[handle] as FileRef;
	var inst : Object;
	if( ref.staticInstance == null ) ref.staticInstance = new Dictionary( true );
	inst = ref.staticInstance[className];
	if( inst == null ){
	var C : Class = ref.appDomain.getDefinition(className) as Class;
	inst = ref.staticInstance[className] = new C();
	}
	return inst;
}

private var totalLoaders : Int = 0;
private var pendingLoaders : Int = 0;
private var onCompleteCB : Function;
private var progressListener : SigSlot;
public static function loadList( load : Array, cb : Function, progressListener:SigSlot=null ) : Void {
	if( !load || !load.length )
	{
	cb();
	return;
	}

	instance.progressListener = progressListener;
	_instance.totalLoaders = instance.pendingLoaders = load.length;
	_instance.onCompleteCB = cb;
	for( var key:String in load )
	{
	var val:Object = load[key];
	var ref:FileRef = new FileRef(val);
	load[key] = ref;
	_fileIndex[ ref.handle ] = ref;
	if( Oboe.flags["SLOW_LOAD"] )
	{
		setTimeout( ref.load, 100 + Math.random()*1000 );
	}	
	else
	{
		ref.load();
	}
	}
}

private function onLoad() : Void
{
	this.pendingLoaders--;
	if( this.progressListener )
	{
	this.progressListener.message( "onProgress", 1 - this.pendingLoaders / this.totalLoaders );
	}
	if( !this.pendingLoaders && this.onCompleteCB != null )
	{
	this.onCompleteCB();
	}
}

}